(function () {
  // 页面的加载性能
  // 各个资源的加载性能
  // 错误监控数据
  const monitor = {
    performance: {
      domComplete: "", // dom 完成时间
      duration: "", // 整个页面加载完成时间 ?
      responseEnd: "", // 请求响应结束时间
    },
    resources: [],
    errors: [],
  };

  function print_PerformanceEntries() {
    // 获取所有内容
    var p = performance.getEntries();
    // 单独处理第一条， 页面的PerformanceNavigationTiming 信息
    let PerformanceTiming = p?.[0];
    if (p?.[0]) {
      monitor.performance.domComplete = PerformanceTiming.domComplete;
      monitor.performance.duration = PerformanceTiming.duration;
      monitor.performance.responseEnd = PerformanceTiming.responseEnd;
    } else {
      console.log(
        performance.timing.domComplete,
        "performance.timing.domComplete"
      );
      console.log(
        performance.timing.navigationStart,
        "performance.timing.navigationStart"
      );
      monitor.performance.domComplete =
        performance.timing.domComplete - performance.timing.navigationStart;
    }
    // 遍历 内容拿出数据
    for (var i = 1; i < p.length; i++) {
      // console.log("PerformanceEntry[" + i + "]");
      print_PerformanceEntry(p[i]);
    }

    setTimeout(() => {
      console.log(monitor);
      postData(monitor);
    }, 0);
  }
  function print_PerformanceEntry(perfEntry) {
    // 先只拿这几个属性
    var properties = ["name", "entryType", "startTime", "duration"];
    let propertyItem = {};

    for (var i = 0; i < properties.length; i++) {
      let hasProperty = properties[i] in perfEntry;
      if (hasProperty) {
        propertyItem[properties[i]] = perfEntry[properties[i]];
      } else {
        console.log("... " + properties[i] + " is NOT supported");
      }
    }
    monitor.resources.push(propertyItem);
  }
  // todo: 
  window.onload = () => {
    print_PerformanceEntries();
  };

 
  // todo:  monitor.errors[i] 的格式保持一致，
 // 因为各个错误返回的格式不一致，为了方便解析，应该要根据特点，封装成一套数据结构
//  message：错误消息
// stack：调用栈
// filename：文件名
// lineNo：行号
// colNo：列号

// todo: onerror 和 error 有重复 需要做下处理，减少重复上报

  // js error
  window.onerror = (url, msg, row, col) => {
    console.log(url, msg, row, col);
    monitor.errors.push({
        type: 'onerror',
        reson: {
          baseURI: url,
          src: '',
          href: '',
          msg: msg,
          row,
          col
        },
    });
  };

  // 资源加载错误
  window.addEventListener(
    "error",
    (e) => {
      console.log(e);
      const tag = e.target.localName;
      if (tag === "link") {
        monitor.errors.push({
          type: e.type,
          reson: {
            baseURI: e.target.baseURI,
            src: e.target.href,
          },
        });
      }
      if (tag === "script") {
        monitor.errors.push({
          type: e.type,
          reson: {
            baseURI: e.target.baseURI,
            src: e.target.src,
          },
        });
      }
    },
    true
  );

  // promise 内的错误
  window.addEventListener("unhandledrejection", (e) => {
    console.log(e);
    monitor.errors.push({
      type: e.type,
      reson: e.reason,
    });
  });

 // ajax 的错误 暂时无法捕捉，只能在ajax 、 fetch 的 catch 里面 自定义上报


  // 发送请求
  const postData = (data) => {
    new Image().src = `http://localhost:3004/log/loading.gif?${JSON.stringify(
      data
    )}`;
    //  测试失败的Ajax 的 请求
    // fetch("http://localhost:3004/log/loading.gif", {
    //     method: "POST",
    //     headers: {
    //         "content-type": "application/json",
    //     },
    //     body: JSON.stringify(data), // data信息 就是 onerror 监听得到的数据
    //     }).then(() => {
    //         console.log('success')
    //     }).catch((error) => {
    //         console.log(error, 'ajax error')
    // }); 
  };

  // 暴露出一个全局的埋点方法 
  window.errorPush = function(data) {
    monitor.errors.push({
        type: data.type,
        reson: data.msg,
    });
    postData(data)
  }
  // todo： 各种类型的提交埋点的方法

})();
